#include <cmath>
#include <string>
#include <GL/gl.h>
#include <GL/glu.h>

#include <SRL/Utils/Core.h>

namespace srl {
    
    // Make the OpenGL texture id
    Texture::Texture() {
        glGenTextures(1, &mId);
        mTarget = GL_TEXTURE_2D;
        mFormat = GL_RGBA;
        mWidth = 1024;
        mHeight = 1024;
        mInternalFormat = GL_RGBA8;
        mType = GL_UNSIGNED_BYTE;
        Bind();
        MakeGLTex();
    }
    Texture::Texture(GLuint id) {
        mId = id;
        Test();
    }
    Texture::Texture(const srl::Texture &t) {
    	mId = t.mId;
        Test();
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mWidth);
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mHeight);
        mFormat = GL_RGBA;
    }
    
    // Delete OpenGL texture id
    Texture::~Texture() {
        glDeleteTextures(1, &mId);
    }
    
    //Bind the texture
    void Texture::Bind() {
        glBindTexture(mTarget, mId);
    }
    void Texture::DBind() {
        glBindTexture(mTarget, 0);
    }
    void Texture::BindFBO(GLenum attachment) {
    	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, mTarget, mId, 0);
    }
    
    // Generate the mipmap with the mipmap ext
    void Texture::GenerateMipmap() {
    	glBindTexture(mTarget, mId);
    	glGenerateMipmapEXT(mTarget);
    }
    
    // Specify image of the texture to OpenGL
    void Texture::MakeGLTex() {
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        
        glTexImage2D(mTarget, 0, mInternalFormat, mWidth, mHeight, 0, mFormat, mType, NULL);
    }
    bool Texture::Test() {
    	int isTex = glIsTexture(mId);
    	
    	if(isTex != GL_TRUE)
    		SRL_Except("L'id utilisé par la srl::Texture ne correspond pas à un identifiant de texture");
    		
    	return isTex == GL_TRUE;
    }
};
